package com.dc.base.ui.fragment

import android.app.Activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.dc.base.vm.BaseViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.lang.reflect.ParameterizedType

abstract class BaseVmFragment<VM : BaseViewModel> : Fragment() {

    protected lateinit var mActivity: Activity

    protected lateinit var mViewModel: VM

    private var isLoaded = false

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(layoutId(), container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mActivity = requireActivity()
        mViewModel = createViewModel()
        initView(view)
        initData()
        createObserver()
        registerUiLoadingChange()
    }

    override fun onResume() {
        super.onResume()
        if (!isLoaded && !isHidden) {
            isLoaded = true
            lazyLoad()
        }
    }

    /**
     * 没有DataBinding/ViewBinding的布局id
     *
     * @return int
     */
    protected abstract fun layoutId(): Int

    /**
     * 初始化视图
     *
     * @param view View
     */
    protected abstract fun initView(view: View)

    /**
     * 初始化数据
     */
    protected abstract fun initData()

    /**
     * 创建LiveData数据观察者
     */
    protected open fun createObserver() {}

    /**
     * 懒加载，只有在Fragment第一次创建且第一次对用户客户就加载
     */
    protected open fun lazyLoad() {}

    private fun registerUiLoadingChange() {
        mViewModel.UiLoadingChange().showLoadingDialog.observe(viewLifecycleOwner, Observer {
            showLoading(it)
        })

        mViewModel.UiLoadingChange().dismissLoadingDialog.observe(viewLifecycleOwner, Observer {
            dismissLoading()
        })
    }

    protected open fun showLoading(message: String = "请求网络中...") {
    }

    protected open fun dismissLoading() {
    }

    /**
     * 耗时任务处理
     */
    protected fun <T> launch(
        block: suspend () -> T,
        onSuccess: (T) -> Unit = {},
        onError: (Throwable) -> Unit = {}
    ) = lifecycleScope.launch {
        runCatching {
            withContext(Dispatchers.IO) {
                block()
            }
        }.onSuccess {
            onSuccess(it)
        }.onFailure {
            onError(it)
        }
    }

    private fun createViewModel(): VM {
        val type = javaClass.genericSuperclass as ParameterizedType
        val arguments = type.actualTypeArguments
        return ViewModelProvider(this).get(arguments[0] as Class<VM>)
    }
}